

import crypto from '../utils/crypto';
import * as express from 'express';
import db from '../utils/db';
import http from '../utils/http';


//获取类型声明//
import configs_win from '../configs_win';
const HALL_SERVER_TYPE = configs_win.hall_server();
type HST = typeof HALL_SERVER_TYPE;
//获取类型声明//

import {gameServerInfoType} from '../game_server/http_service';

const app = express();
let config: HST = null;
let serverMap:{[key:string]:gameServerInfoType} = {
    
};


app.all('*', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By", '3.2.1');
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});
//负载均衡
function chooseServer() {
    var serverinfo: gameServerInfoType = null;
    for (let s in serverMap) {

        let info = serverMap[s];

        if (serverinfo == null) {
            serverinfo = info;
        }
        else {
            if (serverinfo.load > info.load) {
                serverinfo = info;
            }
        }
    }
    return serverinfo;
}

app.get('/register_gs', (req, res) => {

    const ip = req.ip;
    const clientIp = req.query.clientIp;
    const clientPort = req.query.clientPort;
    const httpPort = req.query.httpPort;
    const load = req.query.load;
    const id = clientIp + ':' + clientPort;

    if (serverMap[id]) {
        const info = serverMap[id];
        if (info.clientPort != clientPort || info.httpPort != httpPort || info.ip != ip) {
            http.send(res, 1, '复制gsid:' + id);
            return;
        }
        info.load = load;
        http.send(res, 0, 'ok', { ip });
        return;
    }

    serverMap[id] = {
        ip,
        id,
        clientIp,
        clientPort,
        httpPort,
        load,
    };
    http.send(res, 0, 'ok', { ip });
    console.log('游戏服务器已注册。\n\tid:' + id + '\n\t地址:' + ip + '\n\thttp端口:' + httpPort + '\n\tsocket端口:' + clientPort);


    const reqdata: ret = {
        serverid: id,
        sign: crypto.md5(id + config.ROOM_PRI_KEY)
    };

    http.get(ip, httpPort, '/get_server_info', reqdata, (ret, data) => {
        if (ret && data.errcode == 0) {
            for (let i = 0, l = data.userroominfo.length; i < l; i += 2) {
                let userId = data.userroominfo[i];
                let roomId = data.userroominfo[i + 1];
            }
        }
        else {
            console.log(data.errmsg);
        }
    });
});

export default class Room_service{

    static start($config:HST){
        config = $config;
        app.listen(config.ROOM_PORT, config.FOR_ROOM_IP);
        console.log('房间服务器运行在：' + config.FOR_ROOM_IP + ':' + config.ROOM_PORT);
    }


    static createRoom(account, userId, roomConf, fnCallback: (errorcode: ret & null&number, data:ret&null) => void){
        
        const serverinfo = chooseServer();
        if(serverinfo == null){
            fnCallback(101, null);
            return;
        }

        db.get_gems(account, data => {

            if(data != null){
                const reqdata: ret = {
                    userid: userId,
                    gems: data.gems,
                    conf: roomConf
                };
                reqdata.sign = crypto.md5(userId + roomConf + data.gems + config.ROOM_PRI_KEY);
                http.get(serverinfo.ip, serverinfo.httpPort, '/create_room', reqdata, (ret, data) => {
                    if(ret){
                        if(data.errcode == 0){
                            fnCallback(0, data.roomid);
                        }
                        else{
                            fnCallback(data.errcode, null);
                        }
                        return;
                    }
                    fnCallback(102, null);
                });
            }
            else{
                fnCallback(103, null);
            }

        });

        
    }


    static enterRoom(userId, name, roomId, fnCallback: (errcode, data:ret) => void){

        let reqdata: ret = {
            userid: userId,
            name: name,
            roomid: roomId,
        };

        reqdata.sign = crypto.md5(userId + name + roomId + config.ROOM_PRI_KEY);

        const checkRoomIsRuning = (serverinfo: gameServerInfoType, roomId, callback) => {
            const sign = crypto.md5(roomId + config.ROOM_PRI_KEY);
            http.get(serverinfo.ip, serverinfo.httpPort, '/is_room_runing', {roomid: roomId, sign: sign}, (ret, data) => {
                if(ret){
                    if(data.errcode === 0 && data.runing){
                        callback(true);
                    }
                    else{
                        callback(false);
                    }
                }
                else{
                    callback(false);
                }
            });
        };

        const enterRoomReq = (serverinfo: gameServerInfoType) => {
            http.get(serverinfo.ip, serverinfo.httpPort, '/enter_room', reqdata, (ret, data:ret) => {
                if(ret){
                    if(data.errcode == 0){
                        db.set_room_id_of_user(userId, roomId, (ret) => {
                            fnCallback(0, {
                                ip: serverinfo.clientIp,
                                port: serverinfo.clientPort,
                                token: data.token,
                            });
                        });
                    }
                    else{
                        fnCallback(data.errcode, null);
                    }
                }
                else{
                    fnCallback(-1, null);
                }
            });
        };

        const chooseServerAndEnter = (serverinfo: gameServerInfoType) => {
            serverinfo = chooseServer();
            if(serverinfo != null){
                enterRoomReq(serverinfo);
            }
            else{
                fnCallback(-1, null);
            }
        };

        db.get_room_addr(roomId, (ret, ip, port) => {
            if(ret){
                const id = ip + ':' + port;
                const serverinfo = serverMap[id];
                if(serverinfo != null){
                    checkRoomIsRuning(serverinfo, roomId, isRuning => {
                        if(isRuning){
                            enterRoomReq(serverinfo);
                        }
                        else{
                            chooseServerAndEnter(serverinfo);
                        }
                    });
                }
                else{
                    chooseServerAndEnter(serverinfo);
                }
            }
            else{
                fnCallback(-2, null);
            }
        });
    }
}


